package com.boesch.electroOffice.presentation.appointment;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.boesch.electroOffice.business.businessObject.AppointmentBusinessObject;
import com.boesch.electroOffice.business.common.BusinessException;
import com.boesch.electroOffice.dataaccess.common.IllegalDataAccessException;
import com.boesch.electroOffice.model.electroOffice.Appointment;
import com.boesch.electroOffice.model.enums.SessionParameter;
import com.boesch.electroOffice.model.enums.SubfunctionIdentifier;
import com.boesch.electroOffice.model.wrapper.AppointmentWrapper;
import com.boesch.electroOffice.utils.MessageUtils;
import com.boesch.electroOffice.utils.PortletUtils;
import com.boesch.electroOffice.utils.UserUtils;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.model.User;

/**
 * This class controls all the data is needed 
 * for the AppointmentList
 * 
 * For more details about the package layering have a look at the documentation
 * of the project  or the project object model pom.xml
 * 
 * @author Ralph Koster
 *
 */
@ManagedBean
@SessionScoped
@Controller
public class AppointmentListController implements Serializable {

	private static final long serialVersionUID = 3481873781755493674L;
	private static final Log log = LogFactoryUtil.getLog(AppointmentListController.class);

	@Autowired
	private AppointmentBusinessObject appointmentBusinessObject;
	@Autowired
	private AppointmentNavigationController appointmentNavigationController;

	private List<AppointmentWrapper> appointments;
	private List<AppointmentWrapper> filteredAppointments;

	private AppointmentWrapper selectedAppointment;

	private boolean appointmentsInitialized;

	public List<AppointmentWrapper> getAppointments() {
		String key = PortletUtils.getSessionAttribute(SessionParameter.SUBFUNCTION_KEY.getValue());
		if (null == appointments || !appointmentsInitialized) {
			try {
				appointments = appointmentBusinessObject.readAllAppointmentWrapperFromDataaccess();
			} catch (IllegalDataAccessException e) {
				log.error("Failed to read appointments from dataaccess", e);
			} catch (BusinessException e) {
				log.error("Failed to read appointments from dataaccess", e);
			}
			appointmentsInitialized = true;
		}

		if (null != key) {
			if (key.equals(SubfunctionIdentifier.MY_APPOINTMENTS.getValue())) {
				return getMyAppointments();
			} else if (key.equals(SubfunctionIdentifier.MY_OPEN_APPOINTMENTS.getValue())) {
				return getMyOpenAppointments();
			} else if (key.equals(SubfunctionIdentifier.MY_CLOSED_APPOINTMENTS.getValue())) {
				return getMyClosedAppointments();
			} else if (key.equals(SubfunctionIdentifier.NOT_ASSIGNED_APPOINTMENTS.getValue())) {
				return getNotAssignedAppointments();
			} else {
				return appointments;
			}
		} else {
			return appointments;
		}
	}

	public void navigateToAppointmentView(ActionEvent actionEvent) {
		PortletUtils.setSessionAttribute(SessionParameter.APPOINTMENT_ID.getValue(), String.valueOf(selectedAppointment.getAppointment().getId()));
		String navigationPath = "/jsf/appointment/appointment_detail.xhtml";
		navigateToPath(navigationPath);
	}

	public void navigateToAppointmentEdit(ActionEvent actionEvent) {
		PortletUtils.setSessionAttribute(SessionParameter.APPOINTMENT_ID.getValue(), String.valueOf(selectedAppointment.getAppointment().getId()));
		String navigationPath = "/jsf/appointment/appointment_form.xhtml";
		navigateToPath(navigationPath);
	}

	public void navigateToMeasurementEdit(ActionEvent actionEvent) {
		PortletUtils.setSessionAttribute(SessionParameter.APPOINTMENT_ID.getValue(), String.valueOf(selectedAppointment.getAppointment().getId()));
		String navigationPath = "/jsf/appointment/measurement/measurement_form.xhtml";
		navigateToPath(navigationPath);
	}

	public void navigateToPdfReader(ActionEvent actionEvent) {
		PortletUtils.setSessionAttribute(SessionParameter.APPOINTMENT_ID.getValue(), String.valueOf(selectedAppointment.getAppointment().getId()));
		PortletUtils.setSessionAttribute(SessionParameter.SUBFUNCTION_KEY.getValue(), SubfunctionIdentifier.APPOINTMENT_PDF.getValue());
		String navigationPath = "/jsf/common/pdf_reader.xhtml";
		navigateToPath(navigationPath);
	}

	public void closeAppointment() {
		if (null != selectedAppointment && null != selectedAppointment.getAppointment()) {
			Appointment appointment = selectedAppointment.getAppointment();
			User currentUser = UserUtils.getCurrentUser();
			try {
				appointmentBusinessObject.closeAppointment(appointment, currentUser);
			} catch (IllegalDataAccessException e) {
				log.error("Failed to close appointment: " + appointment.getId());
				MessageUtils.addErrorMessage("Abschliessen des Auftrags fehlgeschlagen.");
			} catch (BusinessException e) {
				log.error("Failed to close appointment: " + appointment.getId());
				MessageUtils.addErrorMessage("Abschliessen des Auftrags fehlgeschlagen.");
			}
		} else {
			MessageUtils.addWarnMessage("Bitte wählen Sie ein Auftrag aus der Liste.");
		}
	}

	public void openAppointment() {
		if (null != selectedAppointment && null != selectedAppointment.getAppointment()) {
			Appointment appointment = selectedAppointment.getAppointment();
			User currentUser = UserUtils.getCurrentUser();
			try {
				appointmentBusinessObject.openAppointment(appointment, currentUser);
				appointmentsInitialized = false;
			} catch (IllegalDataAccessException e) {
				log.error("Failed to close appointment: " + appointment.getId());
				MessageUtils.addErrorMessage("Abschliessen des Auftrags fehlgeschlagen.");
			} catch (BusinessException e) {
				log.error("Failed to close appointment: " + appointment.getId());
				MessageUtils.addErrorMessage("Abschliessen des Auftrags fehlgeschlagen.");
			}
		} else {
			MessageUtils.addWarnMessage("Bitte wählen Sie ein Auftrag aus der Liste.");
		}
	}

	public List<AppointmentWrapper> getFilteredAppointments() {
		return filteredAppointments;
	}

	public void setFilteredAppointments(List<AppointmentWrapper> filteredAppointments) {
		this.filteredAppointments = filteredAppointments;
	}

	public AppointmentWrapper getSelectedAppointment() {
		return selectedAppointment;
	}

	public void setSelectedAppointment(AppointmentWrapper selectedAppointment) {
		this.selectedAppointment = selectedAppointment;
	}

	public boolean isOneAppointmentSelected() {
		boolean returnValue = false;
		if (null != selectedAppointment) {
			returnValue = true;
		}
		return returnValue;
	}

	public void refreshLists() {
		appointmentsInitialized = false;
		getAppointments();
	}

	public String getNumberOfAppointments(ActionEvent event) {
		String key = (String) event.getComponent().getAttributes().get("key");
		int returnValue = 0;
		if (null == appointments || !appointmentsInitialized) {
			getAppointments();
		}

		if (key.equals(SubfunctionIdentifier.MY_APPOINTMENTS.getValue())) {
			User currentUser = UserUtils.getCurrentUser();
			int count = 0;
			for (AppointmentWrapper appointment : appointments) {
				if (currentUser.getEmailAddress().equals(appointment.getUser().getEmailAddress())) {
					count++;
				}
			}
			returnValue = count;
		}

		if (key.equals(SubfunctionIdentifier.MY_OPEN_APPOINTMENTS.getValue())) {
			User currentUser = UserUtils.getCurrentUser();
			int count = 0;
			for (AppointmentWrapper appointment : appointments) {
				if (null != appointment.getAppointment() && null != appointment.getAppointment().getState()
						&& "Offen".equals(appointment.getAppointment().getState().getName()) && appointment.getUser().getUserId() == currentUser.getUserId()) {
					count++;
				}
			}
			returnValue = count;
		}

		if (key.equals(SubfunctionIdentifier.MY_CLOSED_APPOINTMENTS.getValue())) {
			User currentUser = UserUtils.getCurrentUser();
			int count = 0;
			for (AppointmentWrapper appointment : appointments) {
				if (null != appointment.getAppointment() && null != appointment.getAppointment().getState()
						&& "Geschlossen".equals(appointment.getAppointment().getState().getName()) && appointment.getUser().getUserId() == currentUser.getUserId()) {
					count++;
				}
			}
			returnValue = count;
		}

		if (key.equals(SubfunctionIdentifier.NOT_ASSIGNED_APPOINTMENTS.getValue())) {
			int count = 0;
			for (AppointmentWrapper appointment : appointments) {
				if (1 == appointment.getUser().getUserId()) {
					count++;
				}
			}
			returnValue = count;
		}

		if (key.equals(SubfunctionIdentifier.ALL_APPOINTMENTS.getValue())) {
			returnValue = appointments.size();
		}
		return String.valueOf(returnValue);
	}

	private List<AppointmentWrapper> getMyAppointments() {
		User currentUser = UserUtils.getCurrentUser();
		long currentUserId = currentUser.getUserId();
		List<AppointmentWrapper> myAppointments = new ArrayList<AppointmentWrapper>();
		for (AppointmentWrapper appointment : appointments) {
			if (currentUserId == appointment.getUser().getUserId()) {
				myAppointments.add(appointment);
			}
		}
		return myAppointments;
	}

	private List<AppointmentWrapper> getMyOpenAppointments() {
		User currentUser = UserUtils.getCurrentUser();
		long currentUserId = currentUser.getUserId();
		List<AppointmentWrapper> myOpenAppointments = new ArrayList<AppointmentWrapper>();
		for (AppointmentWrapper appointment : appointments) {
			if (currentUserId == appointment.getUser().getUserId() && null != appointment.getAppointment().getState()
					&& "Offen".equals(appointment.getAppointment().getState().getName())) {
				myOpenAppointments.add(appointment);
			}
		}
		return myOpenAppointments;
	}

	private List<AppointmentWrapper> getMyClosedAppointments() {
		User currentUser = UserUtils.getCurrentUser();
		long currentUserId = currentUser.getUserId();
		List<AppointmentWrapper> myClosedAppointments = new ArrayList<AppointmentWrapper>();
		for (AppointmentWrapper appointment : appointments) {
			if (currentUserId == appointment.getUser().getUserId() && null != appointment.getAppointment() && null != appointment.getAppointment().getState()
					&& "Geschlossen".equals(appointment.getAppointment().getState().getName())) {
				myClosedAppointments.add(appointment);
			}
		}
		return myClosedAppointments;
	}

	private List<AppointmentWrapper> getNotAssignedAppointments() {
		List<AppointmentWrapper> notAssignedAppointments = new ArrayList<AppointmentWrapper>();
		for (AppointmentWrapper appointment : appointments) {
			if (1 == appointment.getUser().getUserId()) {
				notAssignedAppointments.add(appointment);
			}
		}
		return notAssignedAppointments;
	}

	private void navigateToPath(String navigationPath) {
		if (null != selectedAppointment) {
			Integer appointmentId = selectedAppointment.getAppointment().getId();
			PortletUtils.setSessionAttribute(SessionParameter.APPOINTMENT_ID.getValue(), String.valueOf(appointmentId));
			appointmentNavigationController.setAppointmentDetailView(true);
			appointmentNavigationController.setNavigationPath(navigationPath);
		} else {
			MessageUtils.addErrorMessage("Bitte selektieren Sie einen Auftrag aus der Liste!");
		}
	}
}